package com.hjb.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.hjb.entity.Database;
import com.hjb.service.IDatabaseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.ApplicationListener;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.List;
import java.util.Map;

/**
 * @author HuJiaBing
 * @date 2025/7/4 10:00
 * @description 动态数据源注册:在应用启动完成后执行
 */
@Slf4j
@Configuration
public class DynamicDatasourceRegister implements EnvironmentAware, ApplicationListener<ApplicationReadyEvent>, ImportBeanDefinitionRegistrar {

    @Resource
    private IDatabaseService databaseService;

    @Resource
    private DatasourceProperty datasourceProperty;

    private static DataSource defaultDataSource;

    @Override
    public void setEnvironment(Environment environment) {
        String main = Binder.get(environment).bind("datasource.main", String.class).get();
        log.info("主数据源:{}", main);
        // 从配置文件中获取主数据源，
        // 后面会在BeanDefinitionRegister中声明DynamicDatasource bean 的时候将这里的数据源作为默认数据源（与DynamicDatasource bean的defaultTargetDataSource绑定），
        // 在DynamicDatasource bean 实例的afterPropertiesSet方法中会初始化resolvedDefaultDataSource
        DataSourceProperties datasourceProperty = Binder.get(environment).bind("spring.datasource." + main, DataSourceProperties.class).get();
        defaultDataSource = datasourceProperty.initializeDataSourceBuilder().type(DruidDataSource.class).build();
        log.info("配置文件中的主数据源初始化完成...");
    }

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        // 初始化配置文件中的数据源
        Map<String, DataSourceProperties> datasource = datasourceProperty.getDatasource();
        datasource.forEach((k, v) -> {
            DataSource ds = v.initializeDataSourceBuilder().build();
            DynamicDatasource.getDataSourceMap().put(k, ds);
        });
        log.info("初始化配置文件中的数据源初始化完成");
        List<Database> databases = databaseService.listAll();
        DynamicDatasource.batchInit(databases);
        log.info("初始化数据库中的数据源完成...");
    }

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(DynamicDatasource.class);
        beanDefinition.setSynthetic(true);
        MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
        // 给TargetDataSources设置外部引用，用于操作
        propertyValues.addPropertyValue("targetDataSources", DynamicDatasource.getDataSourceMap());
        propertyValues.addPropertyValue("defaultTargetDataSource", defaultDataSource);
        registry.registerBeanDefinition("dynamicDatasource", beanDefinition);
        log.info("动态数据源DynamicDatasource注册完成...");

    }
}
